{
 "cells": [
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "---\n",
    "sidebar_label: Ollama Functions\n",
    "---"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# OllamaFunctions\n",
    "\n",
    "This notebook shows how to use an experimental wrapper around Ollama that gives it the same API as OpenAI Functions.\n",
    "\n",
    "Note that more powerful and capable models will perform better with complex schema and/or multiple functions. The examples below use Mistral.\n",
    "For a complete list of supported models and model variants, see the [Ollama model library](https://ollama.ai/library).\n",
    "\n",
    "## Setup\n",
    "\n",
    "Follow [these instructions](https://github.com/jmorganca/ollama) to set up and run a local Ollama instance.\n",
    "\n",
    "## Usage\n",
    "\n",
    "You can initialize OllamaFunctions in a similar way to how you'd initialize a standard ChatOllama instance:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_experimental.llms.ollama_functions import OllamaFunctions\n",
    "\n",
    "model = OllamaFunctions(model=\"mistral\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can then bind functions defined with JSON Schema parameters and a `function_call` parameter to force the model to call the given function:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "model = model.bind(\n",
    "    functions=[\n",
    "        {\n",
    "            \"name\": \"get_current_weather\",\n",
    "            \"description\": \"Get the current weather in a given location\",\n",
    "            \"parameters\": {\n",
    "                \"type\": \"object\",\n",
    "                \"properties\": {\n",
    "                    \"location\": {\n",
    "                        \"type\": \"string\",\n",
    "                        \"description\": \"The city and state, \" \"e.g. San Francisco, CA\",\n",
    "                    },\n",
    "                    \"unit\": {\n",
    "                        \"type\": \"string\",\n",
    "                        \"enum\": [\"celsius\", \"fahrenheit\"],\n",
    "                    },\n",
    "                },\n",
    "                \"required\": [\"location\"],\n",
    "            },\n",
    "        }\n",
    "    ],\n",
    "    function_call={\"name\": \"get_current_weather\"},\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Calling a function with this model then results in JSON output matching the provided schema:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "AIMessage(content='', additional_kwargs={'function_call': {'name': 'get_current_weather', 'arguments': '{\"location\": \"Boston, MA\", \"unit\": \"celsius\"}'}})"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain_core.messages import HumanMessage\n",
    "\n",
    "model.invoke(\"what is the weather in Boston?\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Using for extraction\n",
    "\n",
    "One useful thing you can do with function calling here is extracting properties from a given input in a structured format:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'name': 'Alex', 'height': 5, 'hair_color': 'blonde'},\n",
       " {'name': 'Claudia', 'height': 6, 'hair_color': 'brunette'}]"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from langchain.chains import create_extraction_chain\n",
    "\n",
    "# Schema\n",
    "schema = {\n",
    "    \"properties\": {\n",
    "        \"name\": {\"type\": \"string\"},\n",
    "        \"height\": {\"type\": \"integer\"},\n",
    "        \"hair_color\": {\"type\": \"string\"},\n",
    "    },\n",
    "    \"required\": [\"name\", \"height\"],\n",
    "}\n",
    "\n",
    "# Input\n",
    "input = \"\"\"Alex is 5 feet tall. Claudia is 1 feet taller than Alex and jumps higher than him. Claudia is a brunette and Alex is blonde.\"\"\"\n",
    "\n",
    "# Run chain\n",
    "llm = OllamaFunctions(model=\"mistral\", temperature=0)\n",
    "chain = create_extraction_chain(schema, llm)\n",
    "chain.run(input)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": ".venv",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
